package sqlitegorm

import (
	"os"
	"path/filepath"
	"strings"
	"sync"

	Log "github.com/cihub/seelog"
	"gopkg.in/ini.v1"

	//"gorm.io/driver/sqlite"//这个驱动需要使用CGO
	"github.com/glebarez/sqlite" //这个驱动不需要使用CGO
	gg "gorm.io/gorm"
	"gorm.io/gorm/logger"
)

type GormDB = *gg.DB

var (
	gormOnce    sync.Once
	globGormDB  *gg.DB            //数据库操作对象
	dbVariables map[string]string //数据库名称映射集合
)

// 初始化
func init() {
	InitDB()
}

// 初始化数据库加载配置
func InitDB() {
	gormOnce.Do(func() {
		root := ""
		exePath, err := os.Executable()
		if err != nil {
			root = "."
		}

		root, _ = filepath.EvalSymlinks(filepath.Dir(exePath))

		configFilePath := strings.Replace(root+"/config/app.ini", "\\", "/", -1)

		_, err = os.Stat(configFilePath) //os.Stat获取文件信息
		if err != nil {
			if !os.IsExist(err) {
				Log.Error("配置文件不存在:", err)
				os.Exit(1)
				return
			}
		}

		cfg, err := ini.Load(configFilePath)
		if err != nil {
			Log.Error("配置文件读取错误:", err)
			os.Exit(1)
		}

		if !cfg.HasSection("DataSource") {
			Log.Debug("配置文件没有DataSource,不进行数据库连接")
			return
		}

		dbVariables = make(map[string]string)

		DbVariables := cfg.Section("DbVariables")
		for i := 0; i < len(DbVariables.Keys()); i++ {
			key := DbVariables.Keys()[i].Name()
			value, _ := DbVariables.GetKey(key)
			if value != nil {
				dbVariables[key] = value.String()
			}
		}

		DataSource := cfg.Section("DataSource")

		dbName := "" //sqlite数据库文件路径和名称
		value, _ := DataSource.GetKey("MainDb")
		if value != nil {
			dbName = value.String()
		}

		PrintSql := false
		value, _ = DataSource.GetKey("PrintSql")
		if value != nil {
			tmp, _ := value.Int()
			PrintSql = tmp == 1
		}

		AutoMigrate := false //是否开启AutoMigrate功能(会创建表、缺失的外键、约束、列和索引)
		value, _ = DataSource.GetKey("AutoMigrate")
		if value != nil {
			tmp, _ := value.Int()
			AutoMigrate = tmp == 1
		}

		dbConfig := &gg.Config{
			DisableForeignKeyConstraintWhenMigrating: !AutoMigrate,
		}

		if PrintSql {
			dbConfig.Logger = logger.Default.LogMode(logger.Info) //开启sql打印
		}

		if strings.HasPrefix(dbName, "./") {
			dbName = strings.Replace(dbName, "./", root+"/", 1)
			dbName = strings.Replace(dbName, "\\", "/", -1)
			dbName = strings.Replace(dbName, "//", "/", -1)
		}

		createFileDir(dbName)
		globGormDB, err = gg.Open(sqlite.Open(dbName), dbConfig)

		if err != nil {
			Log.Error("连接数据库错误:", err)
			return
		}
	})
}

// 取gorm操作对象
func GetDB() GormDB {
	return globGormDB
}

/**
 * 创建文件所在文件夹
 * 注意:必须是文件,否则只能创建出上级路径
 * @param filePath 文件路径
 * @return bool:是否成功(如果路径已经存在则不会创建,但返回true); error:错误信息
 */
func createFileDir(filePath string) (bool, error) {
	path := filepath.Dir(filePath) //获取上级目录
	_, err := os.Stat(path)        //os.Stat获取文件信息
	if err == nil {                //获取成功,说明文件存在
		return true, nil
	}

	if os.IsExist(err) { //再次判断路径是否存在,也可以使用os.IsNotExist(err)来判断是否不存在
		return true, nil
	}

	err = os.MkdirAll(path, os.ModePerm)
	if err != nil {
		return false, err
	}

	return true, nil
}
